from common.models.member import OauthMemberBind
from common.libs.pay.WeCatService import WeChatService
from common.libs.member.CartService import CartService
from common.libs.pay.PayService import PayService
from common.libs.UrlManager import UrlManager
from common.models.member import MemberAddress
from common.libs.Helper import getDictFilterFiled
from common.libs.Helper import selectFilterObj
from common.models.pay import PayOrder
from common.models.pay import PayOrderItem
from web.controllers.api import route_api
from application import db
from common.models.food import Food

from flask import request, g
from flask import jsonify
from decimal import Decimal
import json, datetime


@route_api.route('/order/info', methods=['POST'])
def OrderInfo():
    result = {'code': 200, 'msg': '操作成功', 'data': {}}
    goods_list = []
    resp = request.values

    current_member = g.current_member
    if not current_member:
        result['code'] = -1
        result['msg'] = '请先登入！'
        return jsonify(result)

    params_data = resp.get('data')
    if not params_data:
        result['code'] = -1
        result['msg'] = '未选择任何商品'
        return jsonify(result)
    items = json.loads(params_data)['goods']

    foods_dict = {}
    for item in items:
        foods_dict[item['id']] = item['number']

    # 获取订单物品的id
    foods_id = foods_dict.keys()
    pay_price = Decimal('0.00')
    yun_price = Decimal('10.00')  # 默认运费10元
    foods_list = Food.query.filter(Food.id.in_(foods_id)).all()
    for food in foods_list:
        res = {
            'id': food.id,
            'name': food.name,
            'price': str(food.price),
            'pic_url': UrlManager.buildImageUrl(food.main_image),
            'number': foods_dict[food.id],
        }
        goods_list.append(res)
        pay_price = pay_price + Decimal(str(food.price * int(foods_dict[food.id])))

    # 默认地址
    default_address = MemberAddress.query.filter_by(member_id=current_member.id, is_default=1).first()
    detail = default_address.province_str + default_address.city_str + default_address.area_str + default_address.address
    default_address = {
        'name': default_address.nickname,
        'mobile': default_address.mobile,
        'detail': detail,
    }

    result['data']['goods_list'] = goods_list
    result['data']['yun_price'] = str(yun_price)
    result['data']['pay_price'] = str(pay_price)
    result['data']['total_price'] = str(yun_price + pay_price)
    result['data']['default_address'] = default_address

    return jsonify(result)

@route_api.route('/order/create', methods=['POST'])
def CreatOrder():
    result = {'code': 200, 'msg': '操作成功', 'data': {}}
    resp = request.values
    note = resp.get('note')
    params_data = resp.get('data')
    yun_price = resp.get('yun_price')
    default_address = resp.get('default_address')

    if not params_data:
        result['code'] = -1
        result['msg'] = '提交失败，请重试！'
        return jsonify(result)

    items = json.loads(params_data)['goods']
    type = json.loads(params_data)['type']

    if not items:
        result['code'] = -1
        result['msg'] = '未提交任何商品，请重试！'
        return jsonify(result)

    current_member = g.current_member
    if not current_member:
        result['code'] = -1
        result['msg'] = '下单失败，请登入！'
        return jsonify(result)

    if Decimal(yun_price) < 0:
        result['code'] = -1
        result['msg'] = '下单失败，请重试！'
        return jsonify(result)

    # 创建订单操作
    Pay = PayService()
    result = Pay.CreateOrder(
        current_member.id,
        Decimal(yun_price),
        default_address,
        note, items,
    )
    # 创建成功，删除购物车的物品
    if result['code'] == 200 and type == 'cart':
        CartService.delItem(current_member.id, items)

    return jsonify(result)

@route_api.route('/order/pay', methods=['POST'])
def OrderPay():
    resp = {'code': 200, 'msg': '操作成功~', 'data': {}}
    current_member = g.current_member
    req = request.values
    order_sn = req['order_sn'] if 'order_sn' in req else ''
    pay_order_info = PayOrder.query.filter_by(order_sn=order_sn, member_id=current_member.id).first()
    if not pay_order_info:
        resp['code'] = -1
        resp['msg'] = "系统繁忙。请稍后再试"
        return jsonify(resp)

    # 绑定用户的信息
    oauth_bind_info = OauthMemberBind.query.filter_by(member_id=current_member.id).first()
    if not oauth_bind_info:
        resp['code'] = -1
        resp['msg'] = "系统繁忙。请稍后再试~~"
        return jsonify(resp)

    data = {
        'body': '订餐',  # 商品描述
        'out_trade_no': pay_order_info.order_sn,  # 商户订单号
        'total_fee': int(pay_order_info.total_price * 100),  # 订单总金额，单位为分
        'trade_type': 'APP',  # 交易类型，小程序 JSAPI 时openid必填!
        # 'attach': '附加数据',
        # 'openid': oauth_bind_info.openid
    }

    wechatPay = WeChatService(pay_data=data)
    pay_info = wechatPay.get_pay_info()

    # 保存prepay_id为了后面发模板消息
    pay_order_info.prepay_id = pay_info['prepay_id']
    db.session.add(pay_order_info)
    db.session.commit()

    resp['data']['pay_info'] = pay_info
    return jsonify(resp)

@route_api.route("/order/callback", methods=["POST"])
def orderCallback():
    '''
    测试数据
<xml>
  <appid><![CDATA[wx2421b1c4370ec43b]]></appid>
  <attach><![CDATA[支付测试]]></attach>
  <bank_type><![CDATA[CFT]]></bank_type>
  <fee_type><![CDATA[CNY]]></fee_type>
  <is_subscribe><![CDATA[Y]]></is_subscribe>
  <mch_id><![CDATA[10000100]]></mch_id>
  <nonce_str><![CDATA[5d2b6c2a8db53831f7eda20af46e531c]]></nonce_str>
  <openid><![CDATA[oUpF8uMEb4qRXf22hE3X68TekukE]]></openid>
  <out_trade_no><![CDATA[1420702110978170880]]></out_trade_no>
  <result_code><![CDATA[SUCCESS]]></result_code>
  <return_code><![CDATA[SUCCESS]]></return_code>
  <sign><![CDATA[F16BFF589E9CF577E47605865EA6C15B]]></sign>
  <time_end><![CDATA[20140903131540]]></time_end>
  <total_fee>4050</total_fee>
  <coupon_fee><![CDATA[10]]></coupon_fee>
  <coupon_count><![CDATA[1]]></coupon_count>
  <coupon_type><![CDATA[CASH]]></coupon_type>
  <coupon_id><![CDATA[10000]]></coupon_id>
  <trade_type><![CDATA[JSAPI]]></trade_type>
  <transaction_id><![CDATA[1004400740201409030005092168]]></transaction_id>
</xml>
    '''
    header = {'Content-Type': 'application/xml'}
    result_data = {
        'return_code': 'SUCCESS',
        'return_msg': 'OK'
    }
    wechatPay = WeChatService()
    callback_data = wechatPay.xml_to_dict(request.data)
    sign = callback_data['sign']
    callback_data.pop('sign')
    gene_sign = wechatPay.create_sign(callback_data)

    if sign != gene_sign:
        result_data['return_code'] = result_data['return_msg'] = 'FAIL'
        return wechatPay.dict_to_xml(result_data), header

    if callback_data['result_code'] != 'SUCCESS':
        result_data['return_code'] = result_data['return_msg'] = 'FAIL'
        return wechatPay.dict_to_xml(result_data), header

    order_sn = callback_data['out_trade_no']
    pay_order_info = PayOrder.query.filter_by(order_sn=order_sn).first()
    if not pay_order_info:
        result_data['return_code'] = result_data['return_msg'] = 'FAIL'
        return wechatPay.dict_to_xml(result_data), header

    if int(pay_order_info.total_price * 100) != int(callback_data['total_fee']):
        result_data['return_code'] = result_data['return_msg'] = 'FAIL'
        return wechatPay.dict_to_xml(result_data), header

    if pay_order_info.status == 1:
        return wechatPay.dict_to_xml(result_data), header

    target_pay = PayService()
    # 修改订单表中的订单信息和快递信息,pay_sn为第三方流水号
    target_pay.orderSuccess(pay_order_id=pay_order_info.id, params={"pay_sn": callback_data['transaction_id']})
    # 增加回调记录
    target_pay.addPayCallbackData(pay_order_id=pay_order_info.id, data=request.data)
    # 返回回调结果
    return wechatPay.dict_to_xml(result_data), header

@route_api.route('/order/ops', methods=['POST'])
def orderOps():
    """
    订单确认和取消
    :return:
    """
    res = {'code': 200, 'msg': '操作成功！', 'data': {}}
    resp = request.values
    order_sn = resp.get('order_sn')
    action = resp.get('act')
    current_member = g.current_member
    order_info = PayOrder.query.filter_by(
        member_id=current_member.id, order_sn=order_sn).first()
    if not order_info:
        res['code'] = -1
        res['msg'] = "系统繁忙。请稍后再试~~"
        return jsonify(res)

    # 订单确认收货
    if action == 'confirm':
        order_info.express_status = 1
        order_info.update()
        res['data']['act'] = 'confirm'
        return jsonify(res)

    # 订单取消
    if action == 'cancel':
        target_pay = PayService()
        res = target_pay.orderClose(order_info.id)
        res['data']['act'] = 'cancel'
        return jsonify(res)

@route_api.route('/order/detail')
def orderDetail():
    result = {'code': 200, 'msg': '操作成功', 'data': {}}
    resp = request.values
    id = resp.get('id')
    current_member = g.current_member
    if not current_member:
        result['code'] = -1
        result['msg'] = '请先登入！'
        return jsonify(result)

    pay_order_info = PayOrder.query.filter_by(id=id).first()
    if not pay_order_info:
        result['code'] = -1
        result['msg'] = '系统繁忙，请稍后再试！'
        return jsonify(result)

    goods = []
    pay_order_item_list = PayOrderItem.query.filter_by(pay_order_id=id).all()
    pay_food_ids = selectFilterObj(pay_order_item_list, 'food_id')
    pay_food_mapping = getDictFilterFiled(Food, Food.id, 'id', pay_food_ids)
    for item in pay_order_item_list:
        temp_food = pay_food_mapping[item.food_id]
        res = {
            'name': temp_food.name,
            'price': str(temp_food.price),
            'unit': item.quantity,
            'pic_url': UrlManager.buildImageUrl(temp_food.main_image),
        }
        goods.append(res)
    address = json.loads(pay_order_info.express_info)
    # 超时时间24小时
    deadline = datetime.timedelta(days=1) + pay_order_info.created_time
    info = {
        'order_sn': pay_order_info.order_sn,
        'status': pay_order_info.pay_status,
        'status_desc': pay_order_info.status_desc,
        'deadline':deadline.strftime('%Y-%m-%d %H:%M:%S'),
        'pay_price': str(pay_order_info.pay_price),
        'yun_price': str(pay_order_info.yun_price),
        'total_price': str(pay_order_info.total_price),
        'address': {
            'name': address['name'],
            'mobile': address['mobile'],
            'address': address['detail']
        },
        'goods': goods
    }
    result['data']['info'] = info
    return jsonify(result)
